package com.vdong.trade.trading.service;

import com.alibaba.fastjson.JSON;
import com.vdong.trade.trading.common.contract.AbstractResponse;
import com.vdong.trade.trading.common.context.PaymentContext;
import com.vdong.trade.trading.entity.dto.param.PaymentRequestDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 */
public abstract class BasePayment implements Payment {

    Logger Log = LoggerFactory.getLogger(BasePayment.class);

    public static Map<String, BasePayment> paymentMap = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        paymentMap.put(getPayChannel(), this);
    }

    public abstract void validator(PaymentRequestDTO request);

    /**
     * 创建上下文信息
     *
     * @param request
     * @return
     */
    public abstract PaymentContext createContext(PaymentRequestDTO request);


    /**
     * 为下层的支付渠道的数据做好准备
     *
     * @param request
     * @param context
     */
    public abstract void prepare(PaymentRequestDTO request, PaymentContext context);


    /**
     * 基本业务处理
     *
     * @param request
     * @param context
     * @return
     * @throws Exception
     */
    public abstract AbstractResponse generalProcess(PaymentRequestDTO request, PaymentContext context) throws Exception;

    /***
     * 基本业务处理完成后执行的后续操作
     * @param request
     * @param respond
     * @param context
     * @return
     * @throws
     */
    public abstract void afterProcess(PaymentRequestDTO request, AbstractResponse respond, PaymentContext context);

    /**
     * orderFee:订单金额
     * payChannel:支付方式
     * spbillCreateIp:ip
     * subject:商品名称
     * totalFee:总金额
     * tradeNo:订单号
     * userId:用户id
     *
     * @param request
     * @return 核心处理器
     */
    @Override
    public AbstractResponse process(PaymentRequestDTO request) throws Exception {
        try {
            Log.info("Begin BasePayment.process:[{}]", JSON.toJSONString(request));
            //验证
            this.validator(request);
            //组装参数
            PaymentContext context = this.createContext(request);
            //准备,保存订单数据
            this.prepare(request, context);
            //执行
            AbstractResponse response = this.generalProcess(request, context);
            //善后
            this.afterProcess(request, response, context);
            return response;
        } finally {
            this.finallyProcess();
        }
    }

    /**
     * 获取支付渠道
     *
     * @return
     */
    public abstract String getPayChannel();

    /**
     * 支付后的处理
     *
     * @return
     */
    public abstract void finallyProcess();

}
